#Due to load sequence, this needs to be here instead of in environment.rb
require "classy-inheritance"

module Easel
  if Site.table_exists?
    @@site = Site.find(1)
  end

  def self.site=(site)
    @@site = site
  end

  def self.site
    @@site
  end

  class FolderContent
    attr_accessor :id, :name, :url, :user_group_ids

    def initialize(options = {})
      options.each do |key,value|
        if self.respond_to?(key)
          self.send("#{key}=", value)
        else
          raise ArgumentError, "Unkown FolderContent field"
        end
      end
    end
  end

  class Config
    class << self 
      def top_level_folders
        @@top_level_folders
      end

      def build_top_level_folders
        @@top_level_folders = get_folder_content(Content.top_level_folders)
      end

      def get_folder_content(contents)
        contents.collect{|c| folder_content_from_content(c)}
      end

      def folder_content_from_content(ct)
        Easel::FolderContent.new  :id => ct.presentable_id, :name => ct.name, 
                                  :url => ct.url, 
                                  :user_group_ids => ct.user_group_ids
      end

      # This should, at a minimum, contain the names of all the controllers.
      # Keep these in alphabetical order for easier maintenance
      def reserved_urls
        %w{pictures galleries sites
            contents document_categories documents folders functions home
            messages pages permissions presentable sessions user_groups
            users admin manage}
      end
      private

      if Folder.table_exists?
        Easel::Config.build_top_level_folders
      end

    end # class block
  end # Config

require "easel/menu"

  module Menu
    module Session
      def generate_menu(user_group_ids = [])
        mnu = Easel::Menu::HTML.new
                
        cms_links(user_group_ids).each{|lnk| mnu << lnk }

        gallery_links(user_group_ids).each{|lnk| mnu << lnk }

        management_links.each{|lnk| mnu << lnk }
              
        session[:menu] = mnu.to_html
      end

      def get_menu
        unless session[:menu]
          generate_menu
        end
        session[:menu] 
      end

      def content_allowed?(content, user_group_ids)
        return true if current_user_is_admin?
        user_group_ids ||= []
        # Check to make sure the user_group_ids of the parent folders 
        # are included in the user_group_ids parameter
        content.user_group_ids.each do |ugi|
          return false unless user_group_ids.include?(ugi)
        end
        true
      end

      private

      def cms_links(user_group_ids = [])
        links = []

        Content.top_level_folders.each do |c|
          next unless content_allowed?(c, user_group_ids)
          if c.is_a_folder?
            mg = menu_group(c, user_group_ids)
            links << mg unless mg.menu.empty?
          else
            links << Easel::Menu::Link.new(c.name, "/" + c.url)
          end
        end
        links
      end

      def gallery_links(user_group_ids = [])
        links = []
        Gallery.find(:all).each do |g|
          next unless content_allowed?(g.content, user_group_ids)
          links << Easel::Menu::Link.new(g.name, "/" + g.url)
        end
        links
      end

      def menu_group(c, user_group_ids)
        grp = Easel::Menu::Group.new(c.name)
        c.contents_for_folder.each do |p|
          next unless content_allowed?(p, user_group_ids)
          if p.is_a_folder?
            mg = menu_group(p, user_group_ids)
            grp.menu << mg unless mg.menu.empty?
          else
            grp.menu << Easel::Menu::Link.new(p.name, "/" +  p.url)
          end
        end
        grp
      end


      def management_links
        lnks = []

        if current_user_access_in_group?(:content_management)
          lnks << content_management
        end

        if current_user_access_in_group?(:security_management)
          lnks << security_management
        end
    
        lnks
      end
  
      def content_management
        mnu = Easel::Menu::Group.new("Content")

        mnu << link("Site", site_path(1))
        mnu << link("Galleries", galleries_path)
        mnu << link("Pictures", pictures_path)
        mnu << link("Folders", folders_path)
        mnu << link("Pages", pages_path)
        mnu << link("Documents", document_categories_path) 
        mnu << link("Messages", messages_path) 
        mnu << link("Functions", functions_path)
        
        mnu
      end

      def security_management
        mnu = Easel::Menu::Group.new("Security")
        
        mnu << link("Users", users_path)
        mnu << link('User Groups', user_groups_path)
        mnu << link('Permissions', permissions_path) 
    
        mnu.menu.empty? ? nil : mnu
      end

      def link(name, path)
        #
        # calling url_for to reduce calls as this is an expensive method
        # once this is converted to a string, the subsequent 
        # calls to will be cheap
        #
        p = url_for(path)

        if authorized?(p)
          Easel::Menu::Link.new(name, p)
        end
      end
    end # session
  end # Menu
end # Easel

ActionController::Base.send :include, Easel::Menu::Session

ActionController::Base.send :helper_method, :get_menu
